package p.ithorns.tools.excel.write;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.ExcelWriter;
import cn.idev.excel.write.builder.ExcelWriterBuilder;
import cn.idev.excel.write.handler.WriteHandler;
import cn.idev.excel.write.metadata.WriteSheet;
import cn.idev.excel.write.metadata.fill.FillConfig;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import p.ithorns.tools.excel.exception.ExportException;
import p.ithorns.tools.excel.model.TemplateVo;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * EasyExcel 导出工具类
 *
 * @author -
 * @since 2023/5/31
 */
public class TemplateExporter {

    private final static Logger log = LoggerFactory.getLogger(TemplateExporter.class);

    private TemplateExporter() {
    }

    /**
     * 设置响应
     *
     * @param response -
     * @param fileName -
     */
    public static void setResponse(HttpServletResponse response, String fileName) {
        // 设置响应信息
        // response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        String charset = StandardCharsets.UTF_8.name();
        response.setCharacterEncoding(charset);

        //设置导出文件名称（避免乱码）
        try {
            String name = URLEncoder.encode(fileName.concat(".xlsx"), charset);
            response.setHeader("Content-disposition", "attachment;filename=" + name);
        } catch (UnsupportedEncodingException e) {
            throw new ExportException(e.getMessage());
        }
    }

    /**
     * 【模板导出】（多个sheet页）
     *
     * @param response      HttpServletResponse(必填)
     * @param templatePath  模板路劲(必填)
     * @param fileName      文件名(必填)
     * @param excelBeanList excel模板构建参数集合(必填)
     * @param writeHandlers 写excel处理类
     */
    public static void exportWithTemplates(HttpServletResponse response, String templatePath, String fileName, List<TemplateVo<?>> excelBeanList, List<WriteHandler> writeHandlers) {
        if (CollectionUtils.isEmpty(excelBeanList)) {
            throw new ExportException("数据为空");
        }
        // 填充HttpServletResponse参数
        setResponse(response, fileName);
        try (InputStream inputStream = new ClassPathResource(templatePath).getInputStream()) {
            ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream);
            if (CollectionUtils.isNotEmpty(writeHandlers)) {
                for (WriteHandler writeHandler : writeHandlers) {
                    excelWriterBuilder.registerWriteHandler(writeHandler);
                }
            }
            try (ExcelWriter excelWriter = excelWriterBuilder.build()) {
                // 循环配置集合 填充sheet
                excelBeanList.forEach(excelTemplateBean -> fillSheet(excelWriter, excelTemplateBean));
            }
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new ExportException("导出模板数据失败");
        }
    }

    /**
     * 【模板导出】（多个sheet页）
     *
     * @param response      HttpServletResponse(必填)
     * @param templatePath  模板路劲(必填)
     * @param fileName      文件名(必填)
     * @param excelBeanList excel模板构建参数集合(必填)
     */
    public static void exportWithTemplates(HttpServletResponse response, String templatePath, String fileName, List<TemplateVo<?>> excelBeanList) {
        exportWithTemplates(response, templatePath, fileName, excelBeanList, new ArrayList<>());
    }



    private static void fillSheet(ExcelWriter excelWriter, TemplateVo<?> excelTemplateBean) {
        // 创建sheet
        WriteSheet writeSheet = EasyExcel.writerSheet(excelTemplateBean.getSheetName()).build();
        // 填充其他参数
        if (MapUtils.isNotEmpty(excelTemplateBean.getParamMap())) {
            // 每次使用列表参数时创建一个新行
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter.fill(excelTemplateBean.getParamMap(), fillConfig, writeSheet);
        }
        // 填充列表数据
        excelWriter.fill(excelTemplateBean.getTableList(), writeSheet);
    }

    /**
     * 【模板导出】（多个sheet页）
     *
     * @param file          文件(必填)
     * @param templatePath  模板路劲(必填)
     * @param excelBeanList excel模板构建参数集合(必填)
     * @param writeHandlers 写excel处理类
     */
    public static void exportWithTemplates(File file, String templatePath, List<TemplateVo<?>> excelBeanList, List<WriteHandler> writeHandlers) {
        try (InputStream inputStream = new ClassPathResource(templatePath).getInputStream()) {
            ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(file).withTemplate(inputStream);
            if (CollectionUtils.isNotEmpty(writeHandlers)) {
                for (WriteHandler writeHandler : writeHandlers) {
                    excelWriterBuilder.registerWriteHandler(writeHandler);
                }
            }
            try (ExcelWriter excelWriter = excelWriterBuilder.build()) {
                // 循环配置集合 填充sheet
                excelBeanList.forEach(excelTemplateBean -> fillSheet(excelWriter, excelTemplateBean));
            }
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new ExportException("导出模板数据失败");
        }
    }

    /**
     * 【模板导出】（多个sheet页）
     *
     * @param file          文件(必填)
     * @param templatePath  模板路劲(必填)
     * @param excelBeanList excel模板构建参数集合(必填)
     */
    public static void exportWithTemplates(File file, String templatePath,
                                           List<TemplateVo<?>> excelBeanList) {
        exportWithTemplates(file, templatePath, excelBeanList, new ArrayList<>());
    }

}